package com.hex.ds.em.hcdp.common.utils;


import cn.hutool.core.util.ArrayUtil;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNodeImpl;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * @Package: com.hex.hdtp.scf.oracle.utils
 * @ClassName AntlrUtil
 * @Description: antlr相关工具类
 * @Author: Dong shiyi
 * @Date 2023/6/26 11:10
 * @Version v1.0
 **/
public class AntlrUtil {

    public AntlrUtil() {
        throw new Error("do not create this object");
    }


    /**
     * @Method: assembleChildren <br>
     * @Param: [parseTree] <br>
     * @Return: java.lang.String <br>
     * @Description：拼接节点信息（单一节点下钻）<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/20 19:32 <br>
     * @Version： V1.0<br>
     */
    public static String assembleChildren(final ParseTree parseTree) {
        return queryDesignateChildrenText(parseTree, new StringBuilder());
    }


    /**
     * @Method: queryDesignateParant <br>
     * @Param: [thisParseTree, targetClass] <br>
     * @Return: boolean <br>
     * @Description：向上 查找指定父级class是否存在<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/6/20 11:52 <br>
     * @Version： V1.0<br>
     */
    public static boolean queryDesignateParent(final ParseTree thisParseTree, final Class<?> targetClass) {
        return queryDesignateParent(thisParseTree, targetClass, null);
    }

    /**
     * @Method: queryDesignateParant <br>
     * @Param:
     * @param thisParseTree      当前节点
     * @param targetClass        目标节点
     * @param queryParseTreeOver 查找的结束点，如未设置则到最上层 <br>
     * @Return: boolean <br>
     * @Description：<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/3 13:57 <br>
     * @Version： V1.0<br>
     */
    public static boolean queryDesignateParent(final ParseTree thisParseTree
            , final Class<?> targetClass
            , final Class<?>... queryParseTreeOver) {

        return queryDesignateParentObject(thisParseTree, targetClass, queryParseTreeOver) != null;
    }

    /**
     * @Method: queryDesignateParantObject <br>
     * @Param: [thisParseTree, targetClass, noPathRuleContexts] <br>
     * @Return: org.antlr.v4.runtime.tree.ParseTree <br>
     * @Description：查找指定class的父级对象，无则返回空<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/26 11:54 <br>
     * @Version： V1.0<br>
     */
    public static ParseTree queryDesignateParentObject(final ParseTree thisParseTree
            , final Class<?> targetClass
            , final Class<?>... queryParseTreeOver) {
        final ParseTree thisParseTreeParent = thisParseTree.getParent();
        if (thisParseTreeParent == null) {
            return null;
        } else if (ArrayUtil.isNotEmpty(queryParseTreeOver)
                && ArrayUtil.containsAny(queryParseTreeOver, thisParseTreeParent.getClass())) {
            return null;
        } else if (thisParseTreeParent.getClass() == targetClass) {
            return thisParseTreeParent;
        } else {
            return queryDesignateParentObject(thisParseTreeParent, targetClass, queryParseTreeOver);
        }
    }


    private static List<ParseTree> queryDesignateChildrenOfSumObj(final ParseTree parseTree, final boolean isContains, final Class<?>... classes) {
        final List<ParseTree> resultList = new ArrayList<>(10);
        final Queue<ParseTree> queue = new LinkedList<>();
        queue.offer(parseTree);
        while (!queue.isEmpty()) {
            final ParseTree currNode = queue.poll();
            if (ArrayUtil.isEmpty(classes) || ArrayUtil.contains(classes, currNode.getClass()) == isContains) {
                resultList.add(currNode);
            }

            for (int i = 0; i < currNode.getChildCount(); i++) {
                final ParseTree child = currNode.getChild(i);
                if (!(child instanceof TerminalNodeImpl)) {
                    queue.offer(child);
                }
            }
        }
        return resultList;
    }


    /**
     * @Method: queryDesignateChildrenOfSumText <br>
     * @Param:
     * @param parseTree
     * @param isContains
     * @param classes <br>
     * @Return: java.lang.String <br>
     * @Description：获取<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/8/7 11:44 <br>
     * @Version： V1.0<br>
     */
    private static String queryDesignateChildrenOfSumText(final ParseTree parseTree, final boolean isContains, final Class<?>... classes) {
        final StringBuilder builder = new StringBuilder();
        final Queue<ParseTree> queue = new LinkedList<>();
        queue.offer(parseTree);
        while (!queue.isEmpty()) {
            final ParseTree currNode = queue.poll();
            if (ArrayUtil.isEmpty(classes) || ArrayUtil.contains(classes, currNode.getClass()) == isContains) {
                builder.append(assembleChildren(currNode));
            }

            for (int i = 0, size = currNode.getChildCount(); i < size; i++) {
                final ParseTree child = currNode.getChild(i);
                if (!(child instanceof TerminalNodeImpl)) {
                    queue.offer(child);
                }
            }
        }
        return builder.toString();
    }


    /**
     * @Method: queryDesignateChildrenText <br>
     * @Param: [parseTree, builder] <br>
     * @Return: java.lang.String <br>
     * @Description：获取从当前 parseTree 树状结构中每一个子节点的最后一个节点的 getText，并进行拼凑（单一节点，不会处理同级节点）<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/18 18:08 <br>
     * @Version： V1.0<br>
     */
    public static String queryDesignateChildrenText(final ParseTree parseTree, final StringBuilder builder, Class<?>... noAssembleChildren) {
        final int childCount = parseTree.getChildCount();
        if (childCount == 0 || ArrayUtil.contains(noAssembleChildren, parseTree.getClass())) {
            return "";
        }
        for (int i = 0; i < childCount; i++) {
            final ParseTree child = parseTree.getChild(i);
            if (child.getChildCount() == 0) {
                if (ArrayUtil.contains(noAssembleChildren, child.getClass())) {
                    continue;
                }
                builder.append(child.getText()).append(" ");
            }
            queryDesignateChildrenText(child, builder, noAssembleChildren);
        }
        return builder.toString();
    }

}
